from __future__ import absolute_import, print_function, unicode_literals, division
from future_builtins import * #@UnusedWildImport
if __name__ == '__main__':
    __package__ = b'pyson.schema' #@ReservedAssignment
    import pyson.schema #@UnusedImport

from .schema_class import Schema
from .errors import ValidationError, NoRootError
from .util import get_schemas

class Logical(Schema):
    def __init__(self, left, right, *args, **kwds):
        self.left, self.right = left, right
        super(Logical, self).__init__(*args, **kwds)

    @property
    def subschemas(self):
        return (self.left, self.right)

    def validateroot(self, obj, **kwds):
        for sch in self.subschemas:
            try:
                sch.validateroot(obj, **kwds)
            except NoRootError:
                pass
        else:
            raise NoRootError

    def __contains__(self, obj):
        if obj == self.left or obj == self.right:
            return True
        else:
            ttself = type(self)
            if isinstance(self.left, ttself) and obj in self.left:
                return True
            elif isinstance(self.right, ttself) and obj in self.right:
                return True
            else:
                return False

class AND(Logical):
    '''
    Logical **and** or between two _schemas.
    
    Examples
    --------
    
    >>> AND(Int(), Cte(42)).isvalid(42)
    True
    >>> (Int() & Cte(42)).isvalid(12)
    False
    '''


    def validate(self, obj, **kwds):
        self.left.validate(obj, **kwds)
        self.right.validate(obj, **kwds)

class OR(Logical):
    '''
    Logical **or** between two _schemas.
    
    Examples
    --------
    
    >>> OR(Int(), Number()).isvalid(42)
    True
    >>> (Int() | Str()).isvalid(42.0)
    False
    '''

    def validate(self, obj, **kwds):
        try:
            self.left.validate(obj, **kwds)
        except ValidationError:
            try:
                self.left.validateroot(obj, **kwds)
            except NoRootError:
                pass

        self.right.validate(obj, **kwds)

# Save specialized _schemas into the Schema class
Schema.OR_SCHEMA = OR
Schema.AND_SCHEMA = AND

__all__ = get_schemas(globals())
if __name__ == '__main__':
    from . import *
    import doctest
    doctest.testmod(optionflags=doctest.REPORT_ONLY_FIRST_FAILURE, verbose=0)
